#pragma once

#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <boost/algorithm/string.hpp>
#include "cppjieba/Jieba.hpp"
#include "log.hpp"

namespace ns_util{
    class FileUtil{
    public:
        static bool ReadFile(const std::string &file_path, std::string *out)
        {
            std::ifstream in(file_path, std::ios::in);
            if (!in.is_open()) {
                // std::cerr << "open file " << file_path << " error" << std::endl;
                LOG(Fatal, "ReadFile err, errno: " + std::to_string(errno) + " errstring: " + strerror(errno));
                return false;
            }

            std::string line;
            while (std::getline(in, line)) {  // getline的返回值是一个&，while(bool),本质是因为重载了强制类型转化
                *out += line;
            }

            in.close();
            return true;
        }
    };

    class StringUtil{
    public:
        static void Split(const std::string &target, std::vector<std::string> *out, const std::string &sep)
        {
            // boost split
            boost::split(*out, target, boost::is_any_of(sep), boost::token_compress_on);
        }
    };

    const char* const DICT_PATH = "./dict/jieba.dict.utf8";
    const char* const HMM_PATH = "./dict/hmm_model.utf8";
    const char* const USER_DICT_PATH = "./dict/user.dict.utf8";
    const char* const IDF_PATH = "./dict/idf.utf8";
    const char* const STOP_WORD_PATH = "./dict/stop_words.utf8";
    
    class JiebaUtil {
    private:
        // static cppjieba::Jieba jieba;
        cppjieba::Jieba _jieba;
        std::unordered_map<std::string, bool> _stop_words;
        static JiebaUtil* _instance;

    private:
        JiebaUtil():_jieba(DICT_PATH, HMM_PATH, USER_DICT_PATH, IDF_PATH, STOP_WORD_PATH)
        {}
        JiebaUtil(const JiebaUtil&) = delete;

    public:
        static JiebaUtil* GetInstance()
        {
            static std::mutex mtx;
            if (_instance == nullptr) {
                std::lock_guard<std::mutex> lock(mtx);
                if (_instance == nullptr) {
                    _instance = new JiebaUtil();
                    _instance->InitJiebaUtil();
                }
            }
            return _instance;
        }

        void InitJiebaUtil()
        {
            std::ifstream in(STOP_WORD_PATH);
            if (!in.is_open()) {
                LOG(Fatal, "load stop words file error!");
                return;
            }

            std::string line;
            while (std::getline(in, line)) {
                _stop_words.insert({line, true});
            }
            in.close();
        }

        void CutStringHelper(const std::string &src, std::vector<std::string> *out)
        {
            _jieba.CutForSearch(src, *out);
            for (auto iter = out->begin(); iter != out->end(); ) {
                auto it = _stop_words.find(*iter);
                if (it != _stop_words.end()) {
                    // 说明当前的string时暂停词,需要去掉
                    iter = out->erase(iter);
                }
                else {
                    iter++;
                }
            }
        }

        static void CutString(const std::string &src, std::vector<std::string> *out)
        {
            ns_util::JiebaUtil::GetInstance()->CutStringHelper(src, out);
            // jieba.CutForSearch(src, *out);
        }

    };

    // cppjieba::Jieba JiebaUtil::jieba(DICT_PATH, HMM_PATH, USER_DICT_PATH, IDF_PATH, STOP_WORD_PATH);
    JiebaUtil *JiebaUtil::_instance = nullptr;
}
